'host.bmx

Strict

Import brl.bankstream

Import "tool.bmx"
Import "nodeview.bmx"
Import "quickhelp.bmx"

Const TAB$=Chr(9)
Const QUOTES$=Chr(34)
Const EOL$="~n"

?MacOS
Const DEFAULTFONT$="Courier"
Const DEFAULTFONTSIZE=12
Const HOMEPAGE$="/doc/index.html"
Global SVNCMD$="/usr/local/bin/svn"
Const LABELOFF=2
?
?Win32
Const DEFAULTFONT$="Courier"
Const DEFAULTFONTSIZE=10
Const HOMEPAGE$="/doc/index.html"
Global SVNCMD$="svn"
Const LABELOFF=4
?
?Linux
Const DEFAULTFONT$="Lucida"
Const DEFAULTFONTSIZE=12
Const HOMEPAGE$="/doc/index.html"
Global SVNCMD$="/usr/bin/svn"
'Const HOMEPAGE$="/doc/home.html"
Const LABELOFF=0
?

Const MENUNEW=1
Const MENUOPEN=2
Const MENUCLOSE=3
Const MENUSAVE=4
Const MENUSAVEAS=5
Const MENUSAVEALL=6
Const MENUQUIT=7
Const MENUUNDO=8
Const MENUREDO=9
Const MENUCUT=10
Const MENUCOPY=11
Const MENUPASTE=12
Const MENUSELECTALL=13
Const MENUGOTO=14
Const MENUINDENT=15
Const MENUOUTDENT=16
Const MENUFIND=17
Const MENUFINDNEXT=18
Const MENUREPLACE=19
Const MENUNEXT=20
Const MENUPREV=21
Const MENUBUILD=22
Const MENURUN=23

Const MENUSTEP=24
Const MENUSTEPIN=25
Const MENUSTEPOUT=26
Const MENUSTOP=27

Const MENULOCKBUILD=28
Const MENUUNLOCKBUILD=29
'Const MENUBUILDMODULES=30
'Const MENUBUILDALLMODULES=31

Const MENUQUICKENABLED=32
Const MENUDEBUGENABLED=33
Const MENUGUIENABLED=34
Const MENUCOMMANDLINE=35
'Const MENUSYNCMODS=36
Const MENUIMPORTBB=37
'Const MENUFINDINFILES=38
Const MENUPROJECTMANAGER=39
Const MENUSHOWCONSOLE=40
Const MENUOPTIONS=41

Const MENUHOME=42
Const MENUBACK=43
Const MENUFORWARD=44
Const MENUQUICKHELP=45
Const MENUHELPINDEX=46
Const MENUABOUT=47

Const MENUNEWVIEW=48
Const MENUDOCMODS=49

Const MENUPRINT=50

Const MENUTRIGGERDOCMODS=51
Const MENUTRIGGERSYNCDOCS=52

Const MENUCLOSEALL=53

Const MENUREFRESH=54
Const MENUBROWSE=55
Const MENUSHELL=56
Const MENUPROPS=57

Const MENUUPDATE=58
Const MENUCOMMIT=59

Const MENURECENT=256

Const MENUCUSTOM=32768

'Function OpenString:TStream(s$)
'	Return CreateBankStream(CreateStaticBank(Byte Ptr(s.),s.length))	
'End Function

Function Quote$(a$)		'add quotes to arg if spaces found
	Local	p
	If a.length=0 Return
	If a[0]=34 Return	'already quoted
	p=a.find(" ")
	If p=-1 Return a	'no spaces
	Return Chr(34)+a+Chr(34)		
End Function

Type TPlugin Extends TTool
	Field	host:THost
	Field	shortname$
	Field	filters$[]
	
	Method Initialize(owner:THost)
		host=owner
	End Method
	
	Method SetName(name$,extensions$[]=Null)
		shortname$=name
		filters=extensions
		For Local i=0 Until Len filters
			filters[i]=filters[i].toLower()
		Next
	End Method

	Method FileTypes$()			' "Code Files:bmx,fs;"
		Local f$
		If Not filters Return
		For Local x$=EachIn filters
			If f$ f$=f$+","+x$ Else f$=x$
		Next
		Return f$
	End Method
	
	Method FileFilter$()		'   returns - "Code Files:bmx,fs;"
		Local f$=FileTypes()
		If f$ Return shortname+" Files:"+f$+";"
	End Method
	
	Global	nextcommand=MENUCUSTOM
	Global	CommandToolMap:TMap=New TMap	'string(command),tool for plugin.invoke command

	Method BeginSection(menuname$)
		Local	menu:TGadget
		menu=host.AddMenu(menuname)
		CreateMenu "",0,menu
	End Method
	
	Method AddCommand(menuname$,name$,hotkey=0,modifier=0)
		Local	cmd
		Local	menu:TGadget
		cmd=nextcommand
		nextcommand:+1
		menu=host.AddMenu(menuname)
		CreateMenu name,cmd,menu,hotkey,modifier
		CommandToolMap.Insert String(cmd),Self
		Return cmd		
	End Method
	
	Function InvokeCommand(cmd,argument:Object=Null)
		Local	plugin:TPlugin
		plugin=TPlugIn(CommandToolMap.ValueForKey(String(cmd)))
		Return plugin.Invoke(cmd,argument)
	End Function

	Method Debug$(command$)	'public stderr handler
		Return command
	End Method

	Method Open:Object(path$) Abstract
End Type

Type TEventHandler Extends TTool
	Method OnEvent() Abstract
End Type

Type TToolPanel Extends TEventHandler
	Field	name$,path$
	Field	panel:TGadget
	Field	index
	Field	active
	
	Method Show()
	End Method
End Type

Type TRequester
	Field	host:THost
	Field	window:TGadget,ok:TGadget,cancel:TGadget
	Field	centered

	Method initrequester(owner:THost,label$,w=280,h=128,flags=3)
		host=owner
		window=CreateWindow(label,0,0,w,h,Null,1+64)
'		HideGadget window
		If flags&1 cancel=CreateButton("Cancel",16,ClientHeight(window)-34,80,24,window,BUTTON_CANCEL)
		If flags&2 ok=CreateButton("OK",ClientWidth(window)-16-80,ClientHeight(window)-34,80,24,window,BUTTON_OK)
	End Method
	
	Method Show()
		Local	x,y,w,h,win:Tgadget
		DisableGadget host.window
		If Not centered
			win=host.window		
			w=GadgetWidth(window)
			h=GadgetHeight(window)
			x=GadgetX(win)+(GadgetWidth(win)-w)/2
			y=GadgetY(win)+(GadgetHeight(win)-h)/2
			SetGadgetShape window,x,y,w,h
			centered=True
		EndIf
		ShowGadget window
		If ok ActivateGadget ok Else ActivateGadget window
		host.SetRequester Self
		PollSystem
	End Method
	
	Method Hide()
		EnableGadget host.window
		HideGadget window
'		host.SelectPanel host.currentpanel
		host.SetRequester Null
	End Method

	Method OnEvent()
	End Method
End Type

Global LanguageList:TList=New TList

Type THost Extends TTool
	Field	appname$,appabout$,apppath$

	Field	pluginlist:TList=New TList
	Field	eventhandlers:TList=New TList
	Field	window:TGadget
	Field	helppanel:TToolPanel
	Field	activepanel:TToolPanel
	Field	lockedpanel:TToolPanel
	Field	debugger:TTool
	Field	root:TDataNode
	Field	docroot:TDataNode
	Field	quickenable:TGadget,quickenabled	'menu,state
	Field	debugenable:TGadget,debugenabled	'menu,state
	Field	guienable:TGadget,guienabled	'menu,state
	Field	archiver:TTool
	Field	activerequester:TRequester

	Method Register(plugin:TPlugin)
		pluginlist.addlast plugin
	End Method

	Method AddHandler(handler:TEventHandler)
		eventhandlers.addlast handler
	End Method

	Method SetArchiver(tool:TTool)
		archiver=tool
	End Method
	
	Method InitializePlugins()
		Local	plugin:TPlugin	
		For plugin=EachIn pluginlist
			plugin.Initialize(Self)
		Next	
	End Method

	Method InvokePlugins(cmd$="RESET",arg:Object=Null)
		Local	plugin:TPlugin	
		If Not arg arg=Self
		For plugin=EachIn pluginlist
			plugin.Invoke(cmd,arg)
		Next	
	End Method
		
	Method FileTypes$()
		Local	f$,x$
		For Local plugin:TPlugin=EachIn pluginlist
			x$=plugin.FileTypes()
			If x$ 
				If f$ f$:+x$ Else f$=x$
			EndIf
		Next	
		Return f$.Replace(",","|")
	End Method

	Method FileFilters$(ext$="*")
		Local	f$,ff$,k$,p
		ext=ext.toLower()
		For Local plugin:TPlugin=EachIn pluginlist
			ff$=plugin.FileFilter()
			If ff="" Continue
			p=ff.find(":")
			If ff.find(ext,p)>-1
				f=ff+f
			Else
				f=f+ff
			EndIf
			If p>-1 And p<ff.length-1 k=k+ff[p+1..ff.length-1]+","
		Next	
		k="All Known Files:"+k[..k.length-1]+";"
		If ext="*" f=k+f Else f=f+k
		f$=f+"All Files:*;"
		Return f$
	End Method
		
	Method OpenObject:Object(path$)
		Local	stream:TStream
		Local	plugin:TPlugin
		Local	ext$,p$
		Local	obj:Object
		
		If Not path RuntimeError "host.Open called with no path"

		stream=ReadFile(path)
		If Not stream 
			Notify "Open could not read from "+path
			Return Null
		EndIf
		CloseStream stream

		ext$=ExtractExt(path$).ToLower()
		For plugin=EachIn pluginlist
			For p$=EachIn plugin.filters
				If p$=ext
					obj=plugin.Open(path)
					If obj Return obj
					Exit
				EndIf
			Next
		Next
	End Method
	
	Method Save(path$,data:Object)
' let archiver back up old
		If archiver
			Local pathdata:Object[2]
			pathdata[0]=path
			pathdata[1]=data
			archiver.Invoke "ARCHIVE",pathdata
		EndIf
' now do our own save	
		Local text$=String(data)
		If text 
			SaveText text,path
		Else
			CreateFile path
		EndIf
	End Method
	
	Method CreateTempFile$(ext$)
		Local	path$,temppath$,tempcount
	
'		DebugLog "getting tempdir"
		temppath$=GetStringProperty("TempDir")
		While True
			path=temppath+"/Untitled"+tempcount+"."+ext$		'	".txt"
'			path=host.temppath+"/untitled"+tempcount+ext$		'	".txt"
'			DebugLog "filetyping "+path
			If FileType(path)=0 Exit'Return path			
'			DebugLog "path="+path+" filetype(path)="+FileType(path)			
			tempcount:+1
		Wend		
'		DebugLog "creating file at "+path
		If Not CreateFile(path)
			Notify("Failed to create temp file "+path)
			Return
		EndIf
'		DebugLog "created file at "+path
		Return path		
	End Method
	
	Method AddLink:TDataNode(parent:TDataNode,name$,href$)
		Local	n:TDataNode
		n=parent.AddNode(name)
		href=RealPath(href)
		n.SetAction(Self,"NAVIGATE",href)
		Return n
	End Method
	
	Field	menulist:TList=New TList

	Method AddMenu:TGadget(name$)
		Local	menu:TGadget
		For menu=EachIn menulist
			If MenuText(menu)=name Return menu
			If MenuText(menu).Replace("&","")=name.Replace("&","") Return menu
		Next
		menu=CreateMenu(name,0,WindowMenu(window))
		menulist.AddLast menu
		Return menu
	End Method

' folder operations triggered by right button from project space	
	
	Field	folderops:TMap=New TMap
	Field	foldermenu:TGadget

	Method fileopmenu:TGadget()
		Local op$
		If Not foldermenu
			foldermenu=CreateMenu("folderop",0,Null)
			For op=EachIn folderops.keys()
				CreateMenu op,0,foldermenu			
			Next
'			CreateMenu "&Refresh",TOOLREFRESH,foldermenu
		EndIf
		Return foldermenu
	End Method	

	Method AddFileOperation(name$,tool:TTool)	
		folderops.Insert name,tool
		foldermenu=Null
	End Method


	Method SetTitle(n$) Abstract	
	Method SetRequester(req:TRequester) Abstract

	Method OpenSource:Object(path$) Abstract
	Method DebugSource(path$,line,column) Abstract
	Method IsSourceOpen(path$) Abstract
	Method IsTempPath(path$) Abstract
	Method AddRecent(path$) Abstract

	Const EDITMODE=1
	Const DEBUGMODE=2

	Method SetMode(m) Abstract
	Method DebugExit() Abstract

	Method ProcessError$(line$) Abstract

	Method SetStatus(text$) Abstract
	Method UpdateProgress(message$,value=0) Abstract
	
	Method Help(url$) Abstract

	Method WriteDebug(text$) Abstract
	Method AddPanel(tabpanel:TToolPanel) Abstract	
	Method SelectPanel(panel:TToolPanel) Abstract
	Method RemovePanel(tabpanel:TToolPanel) Abstract
	Method RefreshPanel(tabpanel:TToolPanel) Abstract
	Method RefreshAll() Abstract
	Method RefreshToolbar() Abstract
	
	Method AddNode(datanode:TDataNode) Abstract
	Method SelectView(viewid) Abstract
	
	Method Execute(owner:TTool,cmd$,mess$="",post$="",home=True) Abstract

	Method MainMenu(menu) Abstract

	Method DisableHotkeys() Abstract
	
' deprecated

	Method GetCommandLine$() Abstract
	Method SetCommandLine(text$) Abstract

	Method FullPath$(path$) Abstract
	Method SetCodeNode(code:TDataNode) Abstract
	Method ShowFind(a$) Abstract
					
End Type
